﻿using iTextSharp.text;
using iTextSharp.text.pdf;
using O2S.Components.PDFRender4NET;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using Tools.Model;

namespace Tools.Utils
{
    public class PdfHelper
    {
        /// <summary>
        /// 图片清晰度（值越大值清晰）
        /// </summary>
        public enum Definition
        {
            One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, Eight = 8, Nine = 9, Ten = 10
        }

        private Dictionary<Definition, int> WatermarkHeights
        {
            get
            {
                return new Dictionary<Definition, int>
                {
                    {Definition.One,15 },
                    {Definition.Two,30 },
                    {Definition.Three,40 },
                    {Definition.Four,55 },
                    {Definition.Five,65 },
                    {Definition.Six,80 },
                    {Definition.Seven,90 },
                    {Definition.Eight,105 },
                    {Definition.Nine,115 },
                    {Definition.Ten,130 },
                };
            }
        }

        private void ToImage(PDFFile pdfFile, string saveDirectory, string imageNameFormat, int startPageNum, int endPageNum, ImageFormat format, Definition definition)
        {
            if (!Directory.Exists(saveDirectory))
            {
                Directory.CreateDirectory(saveDirectory);
            }
            for (int i = startPageNum; i <= endPageNum; i++)
            {
                // 直接保存（有水印）
                //Bitmap pageImage = pdfFile.GetPageImage(i - 1, 56 * (int)definition);
                //pageImage.Save(saveDirectory + string.Format(imageNameFormat, i) + "." + format.ToString(), format);
                //pageImage.Dispose();

                Bitmap pageImage = pdfFile.GetPageImage(i - 1, 56 * (int)definition);

                //重新画图以去除水印
                Bitmap newPageImage = new Bitmap(pageImage.Width, pageImage.Height);
                Graphics g = Graphics.FromImage(newPageImage);
                var watermarkHeight = WatermarkHeights[definition];
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(pageImage, new System.Drawing.Rectangle(0, 0, pageImage.Width, pageImage.Height),
                    new System.Drawing.Rectangle(0, watermarkHeight, pageImage.Width, pageImage.Height - watermarkHeight), GraphicsUnit.Pixel);

                newPageImage.Save(saveDirectory + string.Format(imageNameFormat, i) + "." + format.ToString(), format);
                newPageImage.Dispose();
                pageImage.Dispose();
                g.Dispose();
            }

            pdfFile.Dispose();
        }

        /// <summary>
        /// 将PDF文档转换为图片的方法
        /// </summary>
        /// <param name="pdfInputPath">PDF文件路径</param>
        /// <param name="saveDirectory">图片保存目录</param>
        /// <param name="imageNameFormat">生成图片的名字，如："xxx{0}"，占位符{0}表示页码</param>
        /// <param name="startPageNum">从PDF文档的第几页开始转换</param>
        /// <param name="endPageNum">从PDF文档的第几页开始停止转换</param>
        /// <param name="format">设置所需图片格式</param>
        /// <param name="definition">设置图片的清晰度，数字越大越清晰</param>
        public void ConvertPDF2Image(Stream pdfInputPath, string saveDirectory,
            string imageNameFormat, int startPageNum, int endPageNum, ImageFormat format, Definition definition)
        {
            PDFFile pdfFile = PDFFile.Open(pdfInputPath);
            if (startPageNum <= 0)
            {
                startPageNum = 1;
            }

            if (endPageNum > pdfFile.PageCount)
            {
                endPageNum = pdfFile.PageCount;
            }

            if (startPageNum > endPageNum)
            {
                int tempPageNum = startPageNum;
                startPageNum = endPageNum;
                endPageNum = startPageNum;
            }
            ToImage(pdfFile, saveDirectory, imageNameFormat, startPageNum, endPageNum, format, definition);
        }

        /// <summary>
        /// 将1个PDF文档所有页全部转换为图片
        /// </summary>
        /// <param name="pdfInputPath">PDF文件路径</param>
        /// <param name="saveDirectory">图片保存目录</param>
        /// <param name="imageNameFormat">生成图片的名字，如："xxx{0}"，占位符{0}表示页码</param>
        /// <param name="format">设置所需图片格式</param>
        /// <param name="definition">设置图片的清晰度，数字越大越清晰</param>
        public void ConvertAllPDF2Images(string pdfInputPath, string saveDirectory, string imageNameFormat,
            ImageFormat format, Definition definition)
        {
            PDFFile pdfFile = PDFFile.Open(pdfInputPath);
            int startPageNum = 1;
            int endPageNum = pdfFile.PageCount;
            ToImage(pdfFile, saveDirectory, imageNameFormat, startPageNum, endPageNum, format, definition);
        }

        /// <summary>
        /// 获取总页数
        /// </summary>
        /// <param name="pdfInputPath"></param>
        /// <returns></returns>
        public int GetPageCount(string pdfInputPath)
        {
            try
            {
                PDFFile pdfFile = PDFFile.Open(pdfInputPath);
                int count = pdfFile.PageCount;
                pdfFile.Dispose();
                return count;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取指定pdf所转换图片的张数
        /// </summary>
        /// <param name="id">文献id(文件夹名称)</param>
        /// <returns></returns>
        public int GetPdfToImagesCount(string id)
        {
            var path = $"{ System.AppDomain.CurrentDomain.BaseDirectory}/pages/{id}";

            return Directory.Exists(path) ? (new DirectoryInfo(path)?.GetFiles("*.jpeg").Length ?? 0) : 0;
        }


        /// <summary>
        /// 设置Pdf水印
        /// </summary>
        /// <param name="filePath">pdf所在的文件完整路径</param>
        /// <param name="outFilePath">生成水印的pdf文件完整路径</param>
        /// <param name="contents">水印内容</param>
        /// <param name="fontSize">水印字体大小</param>
        /// <returns></returns>
        public void SetWaterMark(string filePath, string outFilePath, List<string> contents, int fontSize = 14)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            FileStream fileStream = null;
            try
            {
                pdfReader = new PdfReader(filePath);
                fileStream = new FileStream(outFilePath, FileMode.Create);
                pdfStamper = new PdfStamper(pdfReader, fileStream);
                int total = pdfReader.NumberOfPages + 1;


                PdfContentByte content;
                BaseFont font = BaseFont.CreateFont($"{AppDomain.CurrentDomain.BaseDirectory}\\Fonts\\SIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                PdfGState gs = new PdfGState();
                float rotation = 45;
                for (int i = 1; i < total; i++)
                {
                    var psize = pdfReader.GetPageSize(i);
                    float width = psize.Width;
                    float height = psize.Height;
                    content = pdfStamper.GetOverContent(i);//在内容上方加水印
                    //content = pdfStamper.GetUnderContent(i);//在内容下方加水印
                    //透明度
                    gs.FillOpacity = 0.5f;
                    content.SetGState(gs);
                    //开始写入文本
                    content.BeginText();
                    content.SetColorFill(BaseColor.LIGHT_GRAY);
                    content.SetFontAndSize(font, fontSize);

                    content.SetTextMatrix(0, 0);
                    var fontWidth = font.GetWidthPoint("智", fontSize);
                    var pageWidth = (int)Math.Ceiling(width);
                    var pageHeight = (int)Math.Ceiling(height);
                    var waterMarkWidth = (int)Math.Ceiling((Math.Cos(Math.PI / 4) * fontWidth + 100));

                    for (int j = 0; j < contents.Count; j++)
                    {
                        var waterMarkHeight = (int)Math.Ceiling(Math.Sin(Math.PI / 4) * (fontWidth * contents[j].Length) + 60);
                        for (int x = 0; x <= pageWidth; x += waterMarkWidth)
                        {
                            for (int y = 0; y <= pageHeight; y += waterMarkHeight)
                            {
                                content.ShowTextAligned(Element.ALIGN_CENTER, contents[j], x, y, rotation);
                            }
                        }
                    }
                    content.EndText();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (pdfStamper != null)
                {
                    pdfStamper.Close();
                }
                if (pdfReader != null)
                {
                    pdfReader.Close();
                }
                if (fileStream != null)
                {
                    fileStream.Close();
                    fileStream.Dispose();
                }
            }
        }

        /// <summary>
        /// 设置Pdf水印（http://t.zoukankan.com/haofaner-p-8779840.html）
        /// </summary>
        /// <param name="filePath">pdf所在的文件完整路径</param>
        /// <param name="outFilePath">生成水印的pdf文件完整路径</param>
        /// <param name="contents">水印内容</param>
        /// <param name="fontSize">水印字体大小</param>
        /// <returns></returns>
        public void SetWaterMark(string filePath, string outFilePath, string content, int fontSize = 14)
        {
            SetWaterMark(filePath, outFilePath, new List<string>() { content }, fontSize);
        }


        /// <summary>
        /// 加图片水印
        /// </summary>
        /// <param name="inputfilepath">上传pdf路径</param>
        /// <param name="outputfilepath">保存处理后的pdf路径</param>
        /// <param name="ModelPicName">图片路径</param>
        /// <param name="number">水印数量（one-一个，covered-铺满）</param>
        /// <param name="location">水印位置(top-内容上面，bottom-内容下面)</param>
        /// <param name="rotation">旋转角度</param>
        /// <param name="layout">布局（1-左上方，2顶部中间，3-右上方，4-左边，5-中间，6-右边，7-左下方，8-底部中间，9-右下方）</param>
        /// <returns></returns>
        public ExcutedResult AddImageWatermarkPDF(string inputfilepath, string outputfilepath, string ModelPicName, string number, string location, string rotation, string layout)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;

            try
            {
                pdfReader = new PdfReader(inputfilepath);
                int numberOfPages = pdfReader.NumberOfPages;

                for (int i = 1; i <= numberOfPages; i++)
                {

                    iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(i);
                    float width = psize.Width;
                    float height = psize.Height;
                    pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create));
                    PdfContentByte waterMarkContent;
                    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(ModelPicName);

                    image.GrayFill = 20;//透明度，灰色填充

                    //image.Rotation;//旋转
                    if (!string.IsNullOrWhiteSpace(rotation))
                    {
                        try
                        {
                            image.RotationDegrees = Convert.ToSingle(rotation);//旋转角度
                        }
                        catch (Exception ex)
                        {
                            return ExcutedResult.Failure("旋转角度填写有误，请填写正确的数值或者不填");
                        }
                    }

                    if (number == "one")
                    {
                        float left = 0;
                        float top = 0;

                        switch (layout)
                        {

                            case "1": //左上角
                                break;

                            case "2":
                                left = (width + image.Width) / 2;
                                break;

                            case "3":
                                left = width - image.Width;
                                break;

                            case "4":
                                top = (height + image.Height) / 2;
                                break;

                            case "5":
                                left = (width + image.Width) / 2;
                                top = (height + image.Height) / 2;
                                break;

                            case "6":
                                left = width - image.Width;
                                top = (height + image.Height) / 2;
                                break;

                            case "7":
                                top = height - image.Height;
                                break;

                            case "8":
                                left = (width + image.Width) / 2;
                                top = height - image.Height;
                                break;

                            case "9":
                                left = width - image.Width;
                                top = height - image.Height;
                                break;
                        }

                        image.SetAbsolutePosition(left, top);

                        if (location == "bottom")
                        {
                            waterMarkContent = pdfStamper.GetUnderContent(i);//内容下层加水印
                        }
                        else
                        {
                            waterMarkContent = pdfStamper.GetOverContent(i);//内容上层加水印
                        }

                        waterMarkContent.AddImage(image);
                    }
                    else
                    {
                        var pageWidth = (int)Math.Ceiling(width);
                        var pageHeight = (int)Math.Ceiling(height);
                        var waterMarkWidth = (int)Math.Ceiling((Math.Cos(Math.PI / 4) * image.Width + 100));

                        var waterMarkHeight = (int)Math.Ceiling(Math.Sin(Math.PI / 4) * (image.Width) + 60);
                        for (int x = 0; x <= pageWidth; x += waterMarkWidth)
                        {
                            for (int y = 0; y <= pageHeight; y += waterMarkHeight)
                            {
                                image.SetAbsolutePosition(x, y);

                                if (location == "bottom")
                                {
                                    waterMarkContent = pdfStamper.GetUnderContent(i);//内容下层加水印
                                }
                                else
                                {
                                    waterMarkContent = pdfStamper.GetOverContent(i);//内容上层加水印
                                }

                                waterMarkContent.AddImage(image);
                            }
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                return ExcutedResult.Failure("程序异常，请刷新后重试");
            }
            finally
            {
                if (pdfStamper != null)
                    pdfStamper.Close();

                if (pdfReader != null)
                    pdfReader.Close();
            }

            return ExcutedResult.Success();
        }

        /// <summary>
        /// 添加普通偏转角度文字水印
        /// </summary>
        /// <param name="inputfilepath">上传pdf路径</param>
        /// <param name="outputfilepath">保存处理后的pdf路径</param>
        /// <param name="waterMarkName">水印文字</param>
        /// <param name="number">水印数量（one-一个，covered-铺满）</param>
        /// <param name="location">水印位置(top-内容上面，bottom-内容下面)</param>
        /// <param name="rotation">旋转角度</param>
        /// <param name="layout">布局（1-左上方，2顶部中间，3-右上方，4-左边，5-中间，6-右边，7-左下方，8-底部中间，9-右下方）</param>
        /// <returns></returns>
        public ExcutedResult AddWordWatermark2PDF(string inputfilepath, string outputfilepath, string waterMarkName, string number, string location, string rotation, string layout)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;

            try
            {
                pdfReader = new PdfReader(inputfilepath);
                pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create));
                var total = pdfReader.NumberOfPages;
                iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
                float width = psize.Width;
                float height = psize.Height;
                float rota = 0;

                if (!string.IsNullOrWhiteSpace(rotation))
                {
                    try
                    {
                        rota = Convert.ToSingle(rotation);
                    }
                    catch (Exception)
                    {
                        return ExcutedResult.Failure("旋转角度填写有误");
                    }
                }

                PdfContentByte content;
                //var a = $"{AppDomain.CurrentDomain.BaseDirectory}\\Fonts\\SIMFANG.TTF"; 
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                BaseFont font = BaseFont.CreateFont($"{AppDomain.CurrentDomain.BaseDirectory}Fonts\\SIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                PdfGState gs = new PdfGState();

                for (int i = 1; i <= total; i++)
                {
                    if (number == "one")
                    {
                        float left = 0;
                        float top = 0;

                        switch (layout)
                        {

                            case "1": //左上角
                                break;

                            case "2":
                                left = (width + waterMarkName.Length) / 2;
                                break;

                            case "3":
                                left = width - waterMarkName.Length;
                                break;

                            case "4":
                                top = (height + 70) / 2;
                                break;

                            case "5":
                                left = (width + waterMarkName.Length) / 2;
                                top = (height + 70) / 2;
                                break;

                            case "6":
                                left = width - waterMarkName.Length;
                                top = (height + 70) / 2;
                                break;

                            case "7":
                                top = height - 70;
                                break;

                            case "8":
                                left = (width + waterMarkName.Length) / 2;
                                top = height - 70;
                                break;

                            case "9":
                                left = width - waterMarkName.Length;
                                top = height - 70;
                                break;
                        }
                        //透明度
                        gs.FillOpacity = 0.5f;

                        if (location == "bottom")
                        {
                            content = pdfStamper.GetUnderContent(i);//内容下层加水印
                        }
                        else
                        {
                            content = pdfStamper.GetOverContent(i);//内容上层加水印
                        }

                        content.SetGState(gs);
                        content.SetGrayFill(0.5f);
                        //开始写入文本
                        content.BeginText();

                        content.SetColorFill(BaseColor.GRAY);
                        content.SetFontAndSize(font, 20);
                        content.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, left+50, top+50, rota);
                        content.EndText();
                    }
                    else
                    {
                        var pageWidth = (int)Math.Ceiling(width);
                        var pageHeight = (int)Math.Ceiling(height);
                        var waterMarkWidth = (int)Math.Ceiling((Math.Cos(Math.PI / 4) * waterMarkName.Length + 100));

                        var waterMarkHeight = (int)Math.Ceiling(Math.Sin(Math.PI / 4) * (waterMarkName.Length) + 60);
                        for (int x = 0; x <= pageWidth; x += waterMarkWidth)
                        {
                            for (int y = 0; y <= pageHeight; y += waterMarkHeight)
                            {

                                if (location == "bottom")
                                {
                                    content = pdfStamper.GetUnderContent(i);//内容下层加水印
                                }
                                else
                                {
                                    content = pdfStamper.GetOverContent(i);//内容上层加水印
                                }

                                content.SetGState(gs);
                                content.SetGrayFill(0.5f);
                                //开始写入文本
                                content.BeginText();

                                content.SetColorFill(BaseColor.GRAY);
                                content.SetFontAndSize(font, 20);
                                content.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, x, y, rota);
                                content.EndText();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (pdfStamper != null)
                    pdfStamper.Close();

                if (pdfReader != null)
                    pdfReader.Close();
            }

            return ExcutedResult.Success();
        }

        /// <summary>
        /// 添加倾斜水印
        /// </summary>
        /// <param name="inputfilepath"></param>
        /// <param name="outputfilepath"></param>
        /// <param name="waterMarkName"></param>
        /// <param name="userPassWord"></param>
        /// <param name="ownerPassWord"></param>
        /// <param name="permission"></param>
        public void setWatermark(string inputfilepath, string outputfilepath, string waterMarkName, string userPassWord, string ownerPassWord, int permission)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;

            try
            {
                pdfReader = new PdfReader(inputfilepath);
                pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create));

                // 设置密码  

                //pdfStamper.SetEncryption(false,userPassWord, ownerPassWord, permission);

                int total = pdfReader.NumberOfPages + 1;
                PdfContentByte content;
                BaseFont font = BaseFont.CreateFont($"{AppDomain.CurrentDomain.BaseDirectory}\\Fonts\\SIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

                PdfGState gs = new PdfGState();

                gs.FillOpacity = 0.2f;//透明度



                int j = waterMarkName.Length;

                char c;

                int rise = 0;

                for (int i = 1; i < total; i++)

                {

                    rise = 500;

                    content = pdfStamper.GetOverContent(i);//在内容上方加水印

                    //content = pdfStamper.GetUnderContent(i);//在内容下方加水印



                    content.BeginText();

                    content.SetColorFill(BaseColor.DARK_GRAY);

                    content.SetFontAndSize(font, 50);

                    // 设置水印文字字体倾斜 开始

                    if (j >= 15)

                    {
                        content.SetTextMatrix(200, 120);

                        for (int k = 0; k < j; k++)
                        {
                            content.SetTextRise(rise);
                            c = waterMarkName[k];
                            content.ShowText(c + "");
                            rise -= 20;
                        }

                    }

                    else

                    {

                        content.SetTextMatrix(180, 100);

                        for (int k = 0; k < j; k++)

                        {

                            content.SetTextRise(rise);

                            c = waterMarkName[k];

                            content.ShowText(c + "");

                            rise -= 18;

                        }

                    }

                    // 字体设置结束

                    content.EndText();

                    // 画一个圆

                    //content.Ellipse(250, 450, 350, 550);

                    //content.SetLineWidth(1f);

                    //content.Stroke();

                }



            }

            catch (Exception ex)

            {

                throw ex;

            }

            finally

            {



                if (pdfStamper != null)

                    pdfStamper.Close();



                if (pdfReader != null)

                    pdfReader.Close();

            }

        }


    }
}
